iT邦幫忙

2025 iThome 鐵人賽

DAY 18
0
Software Development

渲染與GPU編程系列 第 18

Day 17|第一個 WebGPU 專案:環境與初始化

  • 分享至 

  • xImage
  •  

這篇就做一件事:把 網頁上的 <canvas> 交給顯示卡,然後用 WebGPU 把畫面清成你指定的顏色。
你會學到:準備環境 → 建專案骨架 → 取得 Adapter / Device → 設定 Canvas Context(呈現格式)→ 錄一個最簡的「清畫面」指令。


1)WebGPU 是什麼?先建立一個「正確的期待」

  • WebGPU 是瀏覽器裡的低階圖形/計算 API,目的跟原生的 Vulkan/Metal/DX12 很像:把資源/同步/管線講清楚,換取 高效能可預測
  • 跟 WebGL 最大不同:很多「瀏覽器以前幫你做」的事,現在要明確自己做(例如:選擇顯示卡、設定畫布格式、建立管線、管理資源)。
  • 好消息:現代 Chrome / Edge 直接可用;若 navigator.gpuundefined,多半是瀏覽器太舊或沒在「安全環境(https 或 localhost)」執行。

2)開發前小檢查:瀏覽器 & 安全環境

  1. 打開你的瀏覽器(建議 Chrome/Edge 最新版)。
  2. 在 DevTools Console 輸入:navigator.gpu —— 若不是 undefined 就 OK。
  3. 安全環境:WebGPU 只在 HTTPS 或 localhost 生效。直接開本地檔案(file://)常會失敗,所以我們會用一個小型開發伺服器。

3)路線 A:純 HTML 版(最小可跑)

檔案結構

webgpu-hello/
├─ index.html
└─ main.js

index.html

<!doctype html>
<html lang="zh-Hant">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <title>WebGPU Hello</title>
    <style>
      html,body { height:100%; margin:0; background:#0b1220; }
      canvas { width: 100vw; height: 100vh; display:block; }
    </style>
  </head>
  <body>
    <canvas id="gfx"></canvas>
    <script type="module" src="./main.js"></script>
  </body>
</html>

main.js(一步步做初始化+清畫面)

// 1) 取得 WebGPU 入口
if (!('gpu' in navigator)) {
  alert('這個瀏覽器尚未支援 WebGPU,或不是在 https/localhost。');
  throw new Error('WebGPU not supported');
}

// 2) 找一張可用的顯示卡(Adapter),再要一個 Device(邏輯裝置)
const adapter = await navigator.gpu.requestAdapter();
if (!adapter) throw new Error('找不到可用的顯示卡(adapter)');
const device = await adapter.requestDevice();

// 3) 取得 Canvas 的 WebGPU Context,並設定「呈現格式」
const canvas = document.getElementById('gfx');
const context = canvas.getContext('webgpu');

// 推薦:用瀏覽器建議的格式(不同平台會對應正確的色彩格式)
const presentationFormat = navigator.gpu.getPreferredCanvasFormat();

function resizeCanvasToDisplaySize() {
  // 把 CSS 尺寸(視窗大小)換成實際像素大小(含裝置像素比)
  const dpr = Math.min(2, window.devicePixelRatio || 1);
  const width  = Math.floor(canvas.clientWidth  * dpr);
  const height = Math.floor(canvas.clientHeight * dpr);
  if (canvas.width !== width || canvas.height !== height) {
    canvas.width = width;
    canvas.height = height;
  }
  context.configure({
    device,
    format: presentationFormat,
    alphaMode: 'opaque' // 不需要透明合成時,opaque 最高效
  });
}
resizeCanvasToDisplaySize();
window.addEventListener('resize', resizeCanvasToDisplaySize);

// 4) 清畫面(把畫面塗成你想要的顏色)
function frame() {
  const encoder = device.createCommandEncoder();

  // 取得當前可寫入的貼圖(就像 swapchain 的下一張)
  const view = context.getCurrentTexture().createView();

  const pass = encoder.beginRenderPass({
    colorAttachments: [{
      view,
      clearValue: { r: 0.06, g: 0.10, b: 0.18, a: 1.0 }, // 想清成什麼顏色就改這裡
      loadOp: 'clear',   // 進場先清掉上一幀
      storeOp: 'store'   // 出場把結果留下來(呈現)
    }]
  });
  pass.end();

  device.queue.submit([encoder.finish()]);

  requestAnimationFrame(frame);
}
requestAnimationFrame(frame);

啟動小伺服器

# 任何一種都行,選你順手的
npx serve .             # 或
python -m http.server   # 或
npx http-server .

開瀏覽器到顯示的 http://localhost:xxxx,你應該看到一個深藍底的全螢幕畫面(代表 WebGPU 在跑)。


4)為什麼要做「這幾步」?(把名詞和動作對上)

  • Adapter:瀏覽器幫你選到某張實體顯卡(或整合 GPU)——像 Vulkan 的 VkPhysicalDevice
  • Device:你和顯示卡溝通的把手(邏輯裝置)——像 VkDevice。所有資源/指令都從它來。
  • Canvas Context (webgpu):把 <canvas> 接上 WebGPU 管線,之後每一幀用 getCurrentTexture() 拿到「這一幀要呈現」的貼圖。
  • 呈現格式:畫布用的色彩格式(例如 BGRA8)。用 getPreferredCanvasFormat() 就能跨平台拿到最合適的那個。
  • Command Encoder / Render Pass:錄製「這幀要做什麼」的指令。今天我們只錄「清畫面」。
  • Queue.submit:把錄好的指令交給 GPU 執行。

5)最常見 8 個小坑(2 分鐘快速排查)

  1. navigator.gpuundefined:瀏覽器太舊、或不是 https/localhost。先升級、改用 dev server。
  2. 一片黑context.configure 沒呼叫、或 canvas.width/height 沒設定(只有 CSS 不算)。
  3. 尺寸模糊:沒用 devicePixelRatio 做實際像素大小。
  4. 報 ValidationError:例如 colorAttachments 的 viewundefined(忘了 createView())。
  5. 每幀重複 configure:只有在尺寸改變時才需要重新 configure;否則可能造成頓卡。
  6. 背景透明或鋸齒邊界:你想要不透明畫面就把 alphaMode: 'opaque'
  7. 多畫面 Tab 切換後報錯:有時瀏覽器會重置 swapchain;重新 configure 一下就好。
  8. Firefox/Safari 還不穩:不同瀏覽器進度不同;遇到怪錯,先在 Chrome/Edge 驗證。

6)我接下來可以做什麼?

  • 畫第一個三角形:加上 WGSL Shader、Render Pipeline、Vertex Buffer(下一篇就做)。
  • 即時改顏色:用滑桿改 clearValue,或做一個時間函數 sin(t)
  • 顯示卡資訊adapter.features / adapter.limits 看看你能做多大貼圖、多複雜的管線。
  • 型別更舒服:TS 專案已經裝好 @webgpu/types,編輯器會自動提示 API。

7)一句話總結

WebGPU 初始化 就是:確認支援 → 取得 adapter/device → 對 <canvas>context.configure(用建議格式)→ 錄一個清畫面的 render pass → queue.submit
當你看見那片你指定顏色的螢幕,代表你已經走通了最核心的一條路,下一步我們就能把 三角形 畫上去,然後把它變成熟悉的「渲染管線」。


上一篇
Day 16|WebGPU 是什麼?與 WebGL 的差異與優勢
下一篇
Day 18|Compute Shader on Website:WebGPU 的 Storage Buffer(SBO)與 Compute Shader 入門(零基礎友善版)#1
系列文
渲染與GPU編程22
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言